// speech_server的测试客户端实现
// 1. 进行服务发现，发现speech_server的服务器节点地址信息并实例化通信信道。
// 2. 读取语音文件数据。
// 3. 发起语音识别RPC调用，并获取识别结果。

#include "etcd.hpp"
#include "channel.hpp"
#include <gflags/gflags.h>
#include <thread>
#include "aip-cpp-sdk/speech.h"
#include "../build/speech.pb.h"

using namespace mag;

// 定义命令行参数，控制程序的运行模式、日志文件和日志级别
DEFINE_bool(run_mode, false, "程序的运行模式，false-调试； true-发布；");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

// 服务发现相关配置
DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(speech_service, "/service/speech_service", "语音识别服务的路径");

int main(int argc, char *argv[])
{
    // 解析命令行参数
    google::ParseCommandLineFlags(&argc, &argv, true);
    init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    // 1. 构造 Rpc 信道管理对象，用于选择合适的 RPC 信道
    auto sm = std::make_shared<mag::ServiceManager>();

    // 注册服务发现时回调函数
    sm->declared(FLAGS_speech_service);
    auto put_cb = std::bind(&mag::ServiceManager::onServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    auto del_cb = std::bind(&mag::ServiceManager::onServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);

    // 2. 构造服务发现对象，连接到 Etcd 服务注册中心
    mag::Discovery::ptr dclient = std::make_shared<mag::Discovery>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);

    // 3. 通过 Rpc 信道管理对象，获取提供语音识别服务的信道
    auto channel = sm->choose(FLAGS_speech_service);
    if (!channel) {
        // 如果没有获取到可用的信道，等待 1 秒后退出
        std::this_thread::sleep_for(std::chrono::seconds(1));
        return -1;
    }

    // 4. 读取语音文件数据
    std::string file_content;
    aip::get_file_content("16k.pcm", &file_content);  // 从文件中读取 PCM 格式的语音数据
    std::cout << "语音文件大小: " << file_content.size() << " 字节" << std::endl;

    // 5. 构造并发起语音识别的 RPC 调用
    mag::SpeechService_Stub stub(channel.get());  // 创建服务存根对象
    mag::SpeechRecognitionReq req;  // 创建语音识别请求对象
    req.set_speech_content(file_content);  // 设置请求中的语音数据
    req.set_request_id("111111");  // 设置请求 ID

    brpc::Controller *cntl = new brpc::Controller();  // 创建 RPC 控制器，用于管理请求的生命周期
    mag::SpeechRecognitionRsp *rsp = new mag::SpeechRecognitionRsp();  // 创建响应对象，用于接收服务端返回的数据

    // 发起 RPC 调用，调用语音识别服务
    stub.SpeechRecognition(cntl, &req, rsp, nullptr);

    // 检查 RPC 调用是否失败
    if (cntl->Failed()) {
        std::cout << "Rpc 调用失败：" << cntl->ErrorText() << std::endl;
        delete cntl;
        delete rsp;
        std::this_thread::sleep_for(std::chrono::seconds(1));  // 等待一秒后退出
        return -1;
    }

    // 检查语音识别的结果是否成功
    if (!rsp->success()) {
        std::cout << "语音识别失败: " << rsp->errmsg() << std::endl;
        delete cntl;
        delete rsp;
        return -1;
    }

    // 输出识别结果
    std::cout << "收到响应, 请求 ID: " << rsp->request_id() << std::endl;
    std::cout << "语音识别结果: " << rsp->recognition_result() << std::endl;

    // 清理资源
    delete cntl;
    delete rsp;

    return 0;
}
